package com.jxin.mall.member.domain.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.jxin.mall.entity.consts.IntegerConsts;
import com.jxin.mall.member.consts.ServiceLogMsgConsts;
import com.jxin.mall.member.domain.consts.AllianceTypeEnum;
import com.jxin.mall.member.domain.consts.MemberUserFileEnum;
import com.jxin.mall.member.domain.dao.MemberUserMapper;
import com.jxin.mall.member.domain.entity.MemberUser;
import com.jxin.mall.member.domain.entity.example.MemberUserExample;
import com.jxin.mall.member.domain.exception.MemberUserServiceException;
import com.jxin.mall.member.domain.service.MemberUserService;
import com.jxin.mall.member.service.entity.dto.req.UserLoginReqDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * MemberUser表的服务实现类
 * @author  蔡佳新
 * @version 1.0
 * @since   jdk 1.8
 */
@Service("memberUserService")
@Slf4j
public class MemberUserServiceImpl  implements MemberUserService {
    @Resource
    private MemberUserMapper memberUserMapper;
    /**
     * 获取用户信息
     * @param  userLoginReqDTO  账号密码
     * @throws MemberUserServiceException 数据库异常
     * @return {@link MemberUser} 实例
     * @author 蔡佳新
     */
    @Override
    public MemberUser getMemberUserWhenLogin(UserLoginReqDTO userLoginReqDTO) throws MemberUserServiceException{
        final List<MemberUser> memberUserList;
        try {
            memberUserList = memberUserMapper.selectByExample(getLoginExample(userLoginReqDTO));
        } catch (Exception e) {
            throw new MemberUserServiceException(e, MemberUserServiceMsg.LOGIN_DB_ERR, JSONUtil.toJsonStr(userLoginReqDTO));
        }
        if(IntegerConsts.ZERO.equals(memberUserList.size())){
            return null;
        }
        return CollUtil.getFirst(memberUserList);
    }
    /**
     * 根据关联code获取用户信息
     * @param  code         用户关联编码
     * @param  allianceType 关联编码类型
     * @return {@link MemberUser} 实例
     * @throws MemberUserServiceException 1.关联类型超出范围 2.数据库查询异常
     * @author 蔡佳新
     */
    @Override
    public MemberUser getMemberUserByCode(String code, AllianceTypeEnum allianceType) {
        final List<MemberUser> memberUserList;
        final MemberUserExample example = new MemberUserExample();

        switch(allianceType) {
            case QQ:
                example.createCriteria().andQqCodeEqualTo(code);
                break;
            case WX:
                example.createCriteria().andWxCodeEqualTo(code);
                break;
            default:
                throw new MemberUserServiceException(MemberUserServiceMsg.OVER_ALLIANCETYPES_ERR, code, allianceType.getName());
        }

        try {
            memberUserList = memberUserMapper.selectByExample(example);
        } catch (Exception e) {
            throw new MemberUserServiceException(e, MemberUserServiceMsg.GET_BY_CODE_ERR, code, allianceType.getName());
        }
        if(IntegerConsts.ZERO.equals(memberUserList.size())){
            return null;
        }
        return CollUtil.getFirst(memberUserList);
    }
    /**
     * 创建新用户
     * @param  memberUser 用户实例
     * @throws MemberUserServiceException 数据库异常
     * @author 蔡佳新
     */
    @Override
    public void creatMemberUser(MemberUser memberUser) throws MemberUserServiceException{
        try {
             // 密码sha256加密
             memberUser.setPassword(SecureUtil.sha256(memberUser.getPassword()));
             memberUserMapper.insertSelective(memberUser);
        } catch (Exception e) {
            throw new MemberUserServiceException(e, MemberUserServiceMsg.CREAT_USER_ERR, JSONUtil.toJsonStr(memberUser));
        }
    }
    /**
     * 更新用户信息
     * @param  memberUser 用户实例
     * @return 创建成功返回 <code>true</code>
     * @throws MemberUserServiceException 更新数据库异常
     * @author 蔡佳新
     */
    @Override
    public Boolean updateMemberUserByPrimaryKey(MemberUser memberUser) {
        try {
            return memberUserMapper.updateByPrimaryKey(memberUser) > 0;
        } catch (Exception e) {
            throw new MemberUserServiceException(e, MemberUserServiceMsg.UPDATE_BY_ID_ERR, JSONUtil.toJsonStr(memberUser));
        }
    }
    /**
     * 判断指定属性是否存在数据
     * @param  value          参数
     * @param  memberUserFile 属性类型枚举实例
     * @throws MemberUserServiceException 1.查库异常 2.枚举类实例越界
     * @return 如果存在数据返回 <code>true</code>
     * @author 蔡佳新
     */
    @Override
    public Boolean isExistByField(String value,  MemberUserFileEnum memberUserFile) throws MemberUserServiceException{
        final MemberUserExample memberUserExample = new MemberUserExample();
        final MemberUserExample.Criteria criteria = memberUserExample.createCriteria();
        switch (memberUserFile) {
            case USERNAME:
                criteria.andUsernameEqualTo(value);
                break;
            case PHONE:
                criteria.andPhoneEqualTo(value);
                memberUserExample.or().andUsernameEqualTo(value);
                break;
            case EMAIL:
                criteria.andEmailEqualTo(value);
                memberUserExample.or().andUsernameEqualTo(value);
                break;
            default:
                throw new MemberUserServiceException(MemberUserServiceMsg.OVER_FILE_TYPES_ERR, memberUserFile);
        }

        try {
            final long count = memberUserMapper.countByExample(memberUserExample);
            if(IntegerConsts.ZERO.equals(count)){
                return false;
            }
        } catch (Exception e) {
            throw new MemberUserServiceException(e, MemberUserServiceMsg.Exist_FILE_ERR, value);
        }
        return true;
    }

    //--------------------------------------------------private---------------------------------------------------------

    /**
     * 获取登入操作的查询条件
     * @param  userLoginReqDTO 登入操作的传参
     * @return 登入操作的查询条件
     * @author 蔡佳新
     */
    private MemberUserExample getLoginExample(UserLoginReqDTO userLoginReqDTO) {
        final MemberUserExample result = new MemberUserExample();
        final MemberUserExample.Criteria criteria = result.createCriteria();
        /*
         * 电话不为空时说明电话登入,用电话和密码查.
         * 反之走账号和密码.
         * 密码用sha256加密
         */
        if(StringUtils.isBlank(userLoginReqDTO.getTel())){
            criteria.andUsernameEqualTo(userLoginReqDTO.getUsername());
        }else {
            criteria.andPhoneEqualTo(userLoginReqDTO.getTel());
        }
        criteria.andPasswordEqualTo(SecureUtil.sha256(userLoginReqDTO.getPassword()));
        return result;
    }
    //---------------------------------------------------logMsg---------------------------------------------------------
    /**
     * 日志信息常量的内部类
     * @author  蔡佳新
     * @version 1.0
     */
    private interface MemberUserServiceMsg{
       String LOGIN_DB_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "用户登入,查数据库异常。入参:{}";
       String GET_BY_CODE_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "根据code获取用户信息,查数据库异常。code:{},type:{}";
       String OVER_ALLIANCETYPES_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "关联类型超出范围。code:{},type:{}";
       String CREAT_USER_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "创建用户,插入数据库异常。入参:{}";
       String OVER_FILE_TYPES_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "超出枚举实例范围,请检查API包版本。入参:{}";
       String Exist_FILE_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "校验指定属性是否有数据,查询数据库异常。入参:{}";
       String UPDATE_BY_ID_ERR = ServiceLogMsgConsts.MEMBER_USER_SERVICE + "根据Id更新用户信息失败。入参:{}";
    }
}
